/*-----------------------------------------
// Declaration of the Header files required.
------------------------------------------*/



#include "syscall.h"


/*----------------------------------------------------------
// Declare global variables and Data Structures Below
----------------------------------------------------------*/

#define MAX_NO_OF_CLERKS 5
#define MAX_NO_OF_CASHREGISTERS 5
#define MAX_NO_OF_CUSTOMERS 20
#define MAX_NO_OF_AISLE 10
#define MAX_NO_SB 10
#define FALSE 0
#define TRUE 1


/* status values for cRSt
 * enum cRStEnum{NOT_SET, CLERK_WAITING, CASHREG_WAITING }; */
#define	NOT_SET 			0
#define CLERK_WAITING		1
#define CASHREG_WAITING		2

/*status values for clerstatus
 * enum ckStEnum{CLERK_FREE, CLERK_BUSY, CLERK_ONBREAK, CLERK_COMING_FROM_BREAK}; */
#define CLERK_FREE					0
#define CLERK_BUSY					1
#define CLERK_ONBREAK				2
#define CLERK_COMING_FROM_BREAK		3


#define MAX_NAME_SIZE   	30
/*buffer to hold the names of lock and CV's and MV's*/
char name[MAX_NAME_SIZE];

/*Customer data sturcture*/
typedef struct customer
{
	int noOfItemsToBePurchased;
	int itemsToBePurchased[10];
	int customerReturning;
	/*customer()
	{
		noOfItemsToBePurchased=(int)((GetRand()%10)+1);
		for(int i=0;i<noOfItemsToBePurchased;i++)
		{
			itemsToBePurchased[i]=(int)(GetRand()%10);
		}
		if(GetRand()%5==4){
			customerReturning=true;
		}
		else{
			customerReturning=false;
		}
	}*/

}customerDataTemplate;




/* cashregister data-structure*/

/*typedef struct cashregister
{

	/* only clrkLock[] should access this data member
	int customerAmount;
	/* only mCshRgLk should access this data member
	int totalAmount;
	/*totalsales at this cash counter
	int totalSalesAtCashRegister;

	cashregister(){

		customerAmount = 0;
		totalAmount = 0;
		totalSalesAtCashRegister = 0;
	}
}cashRegisterTemplate;*/

int crCuA[MAX_NO_OF_CASHREGISTERS];
int crTtl[MAX_NO_OF_CASHREGISTERS];
int crTSl[MAX_NO_OF_CASHREGISTERS];


int cuTCtr;
int cRTCtr;
int ckTCtr;
int sbTCtr;

int cusTCtrLk;
int cRgTCtrLk;
int clkTCtrLk;
int sbTCtrLk;

int testcase;
int noOfClerks;		/* values will change dynamically*/
int noOfCashReg;
int noOfCustomers;
int noOfStockBoys;
int noOfAisle;
/*cashRegisterTemplate cashRegister[MAX_NO_OF_CASHREGISTERS];*/
customerDataTemplate customerData[MAX_NO_OF_CUSTOMERS];



int itemsInStoreInfo[MAX_NO_OF_AISLE]={1,2,3,4,5,6,7,8,9,10} ;

/*------------------------------------------------------------------------
 Declare Locks, CV and Monitor Variables for Customer/Clerk Interaction
------------------------------------------------------------------------*/


/*Lock to  print multiple PRINT Syscalls*/
int printLock;

/*Lock for mutual exclusion on entering line.*/
int clrkLnLk;
/*Locks for each clerk interaction.*/
int clrkLock[MAX_NO_OF_CLERKS];
/*condition to wait on a line for checkout*/
int clrkLnCV[MAX_NO_OF_CLERKS];
/*condition to interaction btw one customer and clerk at a time.*/
int clrkTkCV[MAX_NO_OF_CLERKS];
/*Condition Variable for Clerks waiting on a break*/
int clOBrkCV;
/* maintains the length of each line.*/
int ckLL[MAX_NO_OF_CASHREGISTERS];
/*maintains the status of each clerk.*/
int ckSt[MAX_NO_OF_CLERKS];


/*all to be used for checkout process. To be used under clrkLock[i].*/
int itemId[MAX_NO_OF_CLERKS];
/*to notify that the last item will be processed for each customer/clerk/cash register transaction.*/
int lstIt[MAX_NO_OF_CLERKS];
/*to store the value of customer id so that clerk and cash register know who they are serving.*/
int cuId[MAX_NO_OF_CLERKS];
/*to store the total bill amount for each customer/clerk/cash register transaction.*/
int rcBA[MAX_NO_OF_CLERKS];
/* will help each clerk and cash register know if the customer wants to buy or return items.*/
int isCuR[MAX_NO_OF_CLERKS];/*to check if it is buying or returning customer*/
/*to be used with clrkLnLk*/
int sgCk; /* To store Id of clerk who call manager when line is above 4*/




/*------------------------------------------------------------------------
 Declare Locks, CV and Monitor Variables for Clerk/CashRegister Interaction
------------------------------------------------------------------------*/

/*All these variables would be modified with the clrkLock[i]
differnet states a cash register can be in.*/

/*for clerk and cash reg interaction.*/
int cshRgsCV[MAX_NO_OF_CASHREGISTERS];
/*status array for all cash registers.*/
int cRSt[MAX_NO_OF_CASHREGISTERS];


/*------------------------------------------------------------------------------
// Declare Locks, CV and Monitor Variables for Manager/Cash Register Interaction
//------------------------------------------------------------------------------*/

/*Lock for Mutual Exclusion between Manager and Cash Register*/
/*No CV's or Monitor variables between them*/
int mCshRgLk[MAX_NO_OF_CASHREGISTERS];
int amNd[MAX_NO_OF_CASHREGISTERS];/*amount needed by cash register to give to customer returning items*/
int cshRgWCV[MAX_NO_OF_CASHREGISTERS];

/*------------------------------------------------------------------------------
// Declare Locks, CV and Monitor Variables for Customer/StockBoy/Aisle Interaction
//------------------------------------------------------------------------------*/


/* lock to check the status of stock boy maintianing the mutual exclusion.*/
int sbStatLk;
/* sbSt for maintianing the status of each stockboy	-1=free		-2=on break	>=0 In store doing stuff*/
int sbSt[MAX_NO_SB];
/*maintain the length of the customer needing help in each aisle.*/
int aHlpLL[MAX_NO_OF_AISLE];
/* to wait on the aisle for help.*/
int aslHlpCV[MAX_NO_OF_AISLE];

/*access stock room one at time.*/
int stckRmLk;
int stRS;/*to be used with stckRmLk*/
int stckRmCV;

/*access the restock list maintianing the data consistency.*/
int reStckLk;

/*lock for updating the Qty on each aisle.*/
int aslQtyLk[MAX_NO_OF_AISLE];
/*maintain the Qty on each aisle*/
int aslQty[MAX_NO_OF_AISLE];
/*if the Qty on aisle is empty, wait till restocked.*/
int aslEmtCV[MAX_NO_OF_AISLE];


/* Lock for the button when no SB available.*/
int noSBBtLk;
/* customers wait till SB is woken by manager.*/
int noSBBtCV;
/*stock boys wait till SB is woken by manager.*/
int sbOBrkCV;
/* maintains the length of the line waiting on the pushbutton.*/
int noSBLL;

/* lock on each SB.*/
int sbLock[MAX_NO_SB];
/* wait on SB.*/
int sbCV[MAX_NO_SB];
/*For the Customer and SB ping pong.*/
int sbCustQA[MAX_NO_SB][2];


/*------------------------------------------------------------------------------
// Declare Locks, CV and Monitor Variables for Manager Interaction
//------------------------------------------------------------------------------*/

/*Customer waiting when all clerks are on break*/
int custWtCV;/* This CV should be used with clrkLnLk*/
int alCkOB;
/*Clerks signaling manager to wakeup another clerk if their linelength>4*/
int wkUpCk;/* This CV should be used with clrkLnLk*/
/*variable modified by customers and read by manager to make note of end of simulation*/
int tlCuEx;






/*----------------------------------------------
// Functions for all different types of Threads
//----------------------------------------------

//--------Customer Thread Starts Here-----------*/

void Customer()
{
	int threadId;
	int failureProbablity;
	int counter;
	int currentItemId;
	/*For finding the shortest length. Also the Total customers in a line cannot be more than 99999*/
	int shortestLineLength=100000;
	int mySB;
	int *restockItem;
	int itemAisleId,y,i;
	/* For finding the index of the line with shortest length.	*/
	int shortestLineIndex=-1;
	int sbFound=FALSE;

	Acquire(cusTCtrLk);

	threadId=GetMV(cuTCtr);
	Print2("Cust counter is %d: so thread id is %d.\n",GetMV(cuTCtr),threadId);
	SetMV(cuTCtr, (GetMV(cuTCtr)+1));
	Release(cusTCtrLk);

	/*If customer is going to return items then just bypass the item finding code and go to Clerk*/
	if(customerData[threadId].customerReturning){
		Acquire(printLock);
		Print2("Customer [%d] needs to return [%d] no.of items.\n",threadId, customerData[threadId].noOfItemsToBePurchased);
		Release(printLock);
		goto liningForClerk;
	}
	/*===================================Customer's Item Fetching code below===================================*/
	Acquire(printLock);
	Print2("Customer [%d] wants to buy [%d] no.of items. \n",threadId,customerData[threadId].noOfItemsToBePurchased);
	Release(printLock);

	for(currentItemId=0;currentItemId<customerData[threadId].noOfItemsToBePurchased;currentItemId++)
	{
		/* Generating the 25% failure probablity for finding the item.*/
		itemAisleId=customerData[threadId].itemsToBePurchased[currentItemId];
		failureProbablity=(GetRand()%4);
		sbFound=FALSE;

		/*=============================Finding stock boy code below=============================*/
		if(failureProbablity==1)
		{
			/*We need to get help from the stockboy*/
			Acquire(printLock);
			Print2("Customer [%d] is not able to find item [%d] and is searching for StockBoy.\n",threadId,currentItemId);
			Release(printLock);
			Acquire(sbStatLk);

			/* Finding a stockboy for help*/
			counter=0;
			mySB=itemAisleId;

			/*Iterating for each stockboy*/
			while(counter!=noOfStockBoys)
			{

				/*If sbSt >= 0, it indicates that the stockboy is in aisle , so select that stockboy.*/
				if(GetMV(sbSt[mySB])>=0)
				{
					int currentAisleNumber = (GetMV(sbSt[mySB])%MAX_NO_OF_AISLE);
					sbFound=TRUE;
					SetMV(aHlpLL[currentAisleNumber], GetMV(aHlpLL[currentAisleNumber])+1);
					Wait(aslHlpCV[currentAisleNumber],sbStatLk);

					for(y=0;y<noOfStockBoys;y++)
					{
						if((GetMV(sbSt[y]))==(currentAisleNumber+MAX_NO_OF_AISLE))
						{

							SetMV(sbSt[y], GetMV(sbSt[y])-MAX_NO_OF_AISLE);
							mySB=y;
							break;
						}
					}

					/*sbStatLk->Release(); It's redundant since there is release after the while loop*/
					break;
				}
				mySB=(mySB+1)% noOfStockBoys;
				counter++;
			}
			Release(sbStatLk);


			/*=============================No SB. PushButton code below=============================*/

			if(!sbFound)
			{
				/*no stockboy found so push button for help*/
				Acquire(printLock);
				Print1("Customer [%d] looked in all aisle for StockBoy. He is now requesting help by pressing service button.\n",threadId);
				Release(printLock);
				Acquire(noSBBtLk);

				/*Incrementing the length for pushButton queue*/
				SetMV(noSBLL, GetMV(noSBLL)+1);
				Wait(noSBBtCV,noSBBtLk);

				/*Finding the StockBoy with -3 as the status ; this represents he is ready to serve the PushButton*/
				Release(noSBBtLk);

				Acquire(sbStatLk);
				for(i=0;i<noOfStockBoys;i++)
				{
					if(GetMV(sbSt[i]) == -3)
					{

						mySB = i;
						/*Chaging the sbSt back to default -1;so that no other can pick him up*/
						SetMV(sbSt[i], -1);
						break;
					}
				}
				Release(sbStatLk);
				Acquire(sbLock[mySB]);
				SetMV(sbCustQA[mySB][0], threadId);
				/*Set the id of the item u want to ask the stock boy about.*/
				SetMV(sbCustQA[mySB][1], currentItemId);

				/*Asking the Stockboy about item.*/
				Signal(sbCV[mySB],sbLock[mySB]);
				Wait(sbCV[mySB],sbLock[mySB]);
				Release(sbLock[mySB]);
			}
			/*============PushButton Code ends here================*/

			else
			{

				Acquire(sbLock[mySB]);
				/*Set Customer id for StockBoy to knw.*/
				SetMV(sbCustQA[mySB][0], threadId);
				/*Set the id of the item u want to ask the stock boy abt.*/
				SetMV(sbCustQA[mySB][1], currentItemId);
				Acquire(printLock);
				Print2("Customer [%d] is asking for assistance from StockBoy [%d].\n",threadId,mySB);
				Release(printLock);
				/*Asking the Stockboy abt item.*/
				Signal(sbCV[mySB],sbLock[mySB]);
				Wait(sbCV[mySB],sbLock[mySB]);
				Acquire(printLock);
				Print3("Customer [%d] got aisle [%d] from StockBoy [%d].\n",threadId,itemAisleId,mySB);
				Release(printLock);
				Release(sbLock[mySB]);
			}
			/*====================StockBoy interaction code ends here.=====================*/

		} /* end of item not found loop


		///////================Customer fetch the item code below============

		//Acquiring the lock on the aisle where the item has to be pickeup from.*/
		Acquire(aslQtyLk[itemAisleId]);
		/* checking if the aslQty is 0 or not.*/
		if(GetMV(aslQty[itemAisleId])==0)
		{
			/* If 0 then wait for the item to be restocked.*/
			Wait(aslEmtCV[itemAisleId],aslQtyLk[itemAisleId]);
		}
		/*decrementing the Qty by 1.*/

			Acquire(printLock);
			Print3("Customer [%d] is picking item of type [%d] from Aisle [%d].\n",threadId,customerData[threadId].itemsToBePurchased[currentItemId],itemAisleId);
			Release(printLock);


		SetMV(aslQty[itemAisleId], GetMV(aslQty[itemAisleId])-1);

		/*Pushing the item to the list for restocking.*/
		Acquire(reStckLk);
		ListAppend(customerData[threadId].itemsToBePurchased[currentItemId]);
		Release(reStckLk);

		/*Checking if more is available on Aisle to signal to the other Customers in case waiting for same item/aisle.*/
		if(GetMV(aslQty[itemAisleId])>0)
		{
			Signal(aslEmtCV[itemAisleId],aslQtyLk[itemAisleId]);
		}
		Release(aslQtyLk[itemAisleId]);

		/*================Customer fetch the item code ends here==============*/


	} /* end of customer item pickup loop


	///======================End of Customer Fetching all items code here====================


	/////======Finding shortest line and waiting checkout code below========================*/

liningForClerk:/*label for bypassing item finding code for customers returning items*/

	/*Acquire the lock on clerkLine to find the Shortest line length maintaining the mutual exclusion*/
	Acquire(clrkLnLk);

findshortestline:
	/*Find shortest line length and its index*/
	for(i=0; i<noOfClerks; i++)
	{
		if(GetMV(ckSt[i])==CLERK_ONBREAK)
		{
			/*  If Clerk is on break than no need to check his line length.*/
			continue;
		}
		/* Check and compare for finding minimum of line length and corrosponding index*/
		if((GetMV(ckLL[i]))<shortestLineLength)
		{
			shortestLineLength=(GetMV(ckLL[i]));
			shortestLineIndex=i;
		}
	}

	/*Case where all clerks and on break*/
	if(shortestLineIndex==-1)
	{
		/*Alert the manager that all clerks are on break*/
		SetMV(alCkOB, TRUE);
		Wait(custWtCV,clrkLnLk);
		goto findshortestline;

	}

	/*==============Shortest Line found. Waiting for checkout==================

	//If customer finds a line with shortest length that has a clerk who is not on break,
	// increment the line length*/
	Acquire(printLock);
	Print3("Customer [%d] chose Clerk [%d] with line length of [%d].\n",threadId,shortestLineIndex, GetMV(ckLL[shortestLineIndex]));
	Release(printLock);
	SetMV(ckLL[shortestLineIndex], GetMV(ckLL[shortestLineIndex])+1);
	Wait(clrkLnCV[shortestLineIndex],clrkLnLk);

	/*decrease the line length as the one customer will now be served by the clerk.*/
	SetMV(ckLL[shortestLineIndex], GetMV(ckLL[shortestLineIndex])-1);
	Release(clrkLnLk);

	/*Acquire lock on that clerk so that the checkout process is mutually exclusive.*/
	Acquire(clrkLock[shortestLineIndex]);

	/* Give the clerk items one by one.*/
	SetMV(cuId[shortestLineIndex], threadId);
	/*notify the clerk whether the customer is buying or returning items*/
	SetMV(isCuR[shortestLineIndex], customerData[threadId].customerReturning);


	/*=================Entire CheckOut code below===========================*/

	for(i=0;i<customerData[threadId].noOfItemsToBePurchased;i++)
	{

		/* Setting the id of item passed for the clerk to access*/
		SetMV(itemId[shortestLineIndex] , customerData[threadId].itemsToBePurchased[i]);

		/*Checking for the last item in order to notify the clerk.*/
		if(i==(customerData[threadId].noOfItemsToBePurchased)-1)
		{
			SetMV(lstIt[shortestLineIndex], TRUE);

		}
		/* customer will give items one by one to clerk*/
		Acquire(printLock);
		Print3("Customer [%d] gives item [%d] to Clerk [%d].\n",threadId,(i+1),shortestLineIndex);
		Release(printLock);
		Signal(clrkTkCV[shortestLineIndex],clrkLock[shortestLineIndex]);
		if(i==(customerData[threadId].noOfItemsToBePurchased)-1)
		{
			Acquire(printLock);
			Print3("Customer [%d] tells Clerk [%d], I have given you all my [%d] items.\n",threadId,shortestLineIndex,customerData[threadId].noOfItemsToBePurchased);
			Release(printLock);
		}
		Wait(clrkTkCV[shortestLineIndex],clrkLock[shortestLineIndex]);
	}
	if(!customerData[threadId].customerReturning)
		{
		Acquire(printLock);
		Print3("Customer [%d] pays $[%d] to Clerk [%d] and is now waiting for receipt.\n",threadId, GetMV(rcBA[shortestLineIndex]),shortestLineIndex);
		Release(printLock);
		/*Signal the clerk for payment.*/
		Signal(clrkTkCV[shortestLineIndex],clrkLock[shortestLineIndex]);
		Wait(clrkTkCV[shortestLineIndex],clrkLock[shortestLineIndex]);
		Acquire(printLock);
		Print2("Customer [%d] got receipt from Clerk [%d] and is now leaving.\n",threadId,shortestLineIndex);
		Release(printLock);
	}
	else{
		Acquire(printLock);
		Print3("Customer [%d] receives $[%d] from Clerk [%d] and is now waiting for receipt.\n",threadId, GetMV(rcBA[shortestLineIndex]),shortestLineIndex);
		Release(printLock);
		/*Signal the clerk for payment.*/
		Signal(clrkTkCV[shortestLineIndex],clrkLock[shortestLineIndex]);
		Wait(clrkTkCV[shortestLineIndex],clrkLock[shortestLineIndex]);
		Acquire(printLock);
		Print2("Customer [%d] got receipt from Clerk [%d] and is now leaving.\n",threadId,shortestLineIndex);
		Release(printLock);
	}

/*=============CheckOut Over. Customer thread will end soon after reseting values=============///

	//Reseting the values to defaults*/
	SetMV(lstIt[shortestLineIndex], FALSE);
	SetMV(itemId[shortestLineIndex], -1);
	SetMV(cuId[shortestLineIndex], -1);
	SetMV(isCuR[shortestLineIndex], FALSE);
	Release(clrkLock[shortestLineIndex]);
	SetMV(tlCuEx, GetMV(tlCuEx)+1);

	Exit(0);
}

/*============End of Customer Thread Code==================//*/




/*switch case for Sprintf */
void SwitchSprintf(int id, int index)
{

	switch(id){
		case 0:
		{
			name[index] = '0';
			break;
		}
		case 1:
		{
			name[index] = '1';
			break;
		}
		case 2:
		{
			name[index] = '2';
			break;
		}
		case 3:
		{
			name[index] = '3';
			break;
		}
		case 4:
		{
			name[index] = '4';
			break;
		}
		case 5:
		{
			name[index] = '5';
			break;
		}
		case 6:
		{
			name[index] = '6';
			break;
		}
		case 7:
		{
			name[index] = '7';
			break;
		}
		case 8:
		{
			name[index] = '8';
			break;
		}
		case 9:
		{
			name[index] = '9';
			break;
		}
		default:
			Print("Error: Sprintf incorrect id\n");
	}/*end of switch case*/

}

/* Sprintf code */
int Sprintf(char *idName, int id, int len)
{
	int i;
	int id1, id2;
	for(i=0; i<len; i++)
	{
		name[i] = idName[i];
	}
	/*Warning: maximum number for id is 99 */
	if(id<=9){
		SwitchSprintf(id, i);
		i++;
		name[i]='\0';
	}
	else if((id>=10) && (id<=99)){
		id1 = id/10;
		SwitchSprintf(id1, i);
		i++;
		id2 = id%10;
		SwitchSprintf(id2, i);
		i++;
		name[i]='\0';
	}
	else{
		Print("Error: Sprintf incorrect id. greater than 99");
		return -1;
	}
	return i;
}
/*
//============================================
//  Functions for the repeatable test cases
//============================================


//This part of the code generates the common test parameters needed for the simulation to run
// i.e. Condition Variables , Monitors & Locks*/
void generateCmnTestParams()
{
	int i=0,j=0;
	int len;



	Acquire(printLock);
	Print1("\n\nNumber of Clerks = [%d]\n",noOfClerks);
	Print1("Number of StockBoys = [%d]\n",noOfStockBoys);
	Print1("Number of CashRegisters = [%d]\n",noOfCashReg);
	Print1("Number of Customers = [%d]\n",noOfCustomers);
	Print("Number of Managers = [1]\n");
	Print("Number of Aisle = [10]\n");
    Print("Items:\n");
    Print("\tNumber - Price\n");

	for(j=0;j<MAX_NO_OF_AISLE;j++)
	{
		Print2("\t%d  -  %d  \n",j,itemsInStoreInfo[j]);
	}
    Print("\n\n");
	Release(printLock);


	clrkLnLk= CreateLock("clrkLnLk",8);
	sbStatLk = CreateLock("sbStatLk",8);
	stckRmLk = CreateLock("stckRmLk",8);
	stckRmCV = CreateCondition("stckRmCV",8);
	reStckLk = CreateLock("reStckLk",8);
	custWtCV = CreateCondition("custWtCV",8);
	for(i=0;i<MAX_NO_OF_AISLE;i++)
	{
		len = Sprintf("aslQtyLk",i,8);
		aslQtyLk[i]=CreateLock(name , len);

		len = Sprintf("aslEmtCV",i,8);
		aslEmtCV[i]=CreateCondition(name, len);

		len = Sprintf("aslHlpCV",i,8);
		aslHlpCV[i]=CreateCondition(name, len);
	}

	noSBBtLk =CreateLock("noSBBtLk",8);
	noSBBtCV = CreateCondition("noSBBtCV",8);

	sbOBrkCV = CreateCondition("sbOBrkCV",8);
	for(i=0;i<noOfStockBoys;i++)
	{
		len = Sprintf("sbLock",i,6);
		sbLock[i]=CreateLock(name, len);

		len = Sprintf("sbCV",i,4);
		sbCV[i]=CreateCondition(name, len);

	}
	for(i=0;i<noOfClerks;i++)
	{
		len = Sprintf("clrkLock",i,8);
		clrkLock[i]=CreateLock(name, len);

		len = Sprintf("clrkLnCV",i,8);
		clrkLnCV[i]=CreateCondition(name, len);

		len = Sprintf("clrkTkCV",i,8);
		clrkTkCV[i]=CreateCondition(name, len);
	}

	for(i=0;i<noOfCashReg;i++)
	{
		len = Sprintf("cshRgsCV",i,8);
		cshRgsCV[i]=CreateCondition(name, len);

		len = Sprintf("mCshRgLk",i,8);
		mCshRgLk[i]=CreateLock(name, len);

		len = Sprintf("cshRgWCV",i,8);
		cshRgWCV[i]=CreateCondition(name, len);
	}



	clOBrkCV=CreateCondition("clOBrkCV",8);

	for(i=0;i<noOfCustomers;i++)
	{
		customerData[i].noOfItemsToBePurchased=(int)((GetRand()%10)+1);
		for(j=0;j<customerData[i].noOfItemsToBePurchased;j++)
		{
			customerData[i].itemsToBePurchased[j]=(int)(GetRand()%10);
		}
		if(GetRand()%5==4){
			customerData[i].customerReturning=TRUE;
		}
		else{
			customerData[i].customerReturning=FALSE;
		}
	}



	/* Create Monitor variables*/
	cuTCtr = CreateMV("cuTCtr",6,0);
	cRTCtr = CreateMV("cRTCtr",6,0);
	ckTCtr = CreateMV("ckTCtr",6,0);
	sbTCtr = CreateMV("sbTCtr",6,0);

	for(i=0; i<noOfCashReg; i++){
		len = Sprintf("ckLL",i,4);
		ckLL[i] = CreateMV(name, len, 0);
	}

	for(i=0; i<noOfClerks; i++){
		len = Sprintf("ckSt",i,4);
		ckSt[i] = CreateMV(name, len, CLERK_FREE);
	}

	for(i=0; i<noOfClerks; i++){
		len = Sprintf("itId",i,4);
		itemId[i] = CreateMV(name, len, -1);
	}

	for(i=0; i<noOfClerks; i++){
		len = Sprintf("lstIt",i,5);
		lstIt[i] = CreateMV(name, len, FALSE);
	}

	for(i=0; i<noOfClerks; i++){
		len = Sprintf("cuId",i,4);
		cuId[i] = CreateMV(name, len, -1);
	}

	for(i=0; i<noOfClerks; i++){
		len = Sprintf("rcBA",i,4);
		rcBA[i] = CreateMV(name, len, -1);
	}

	for(i=0; i<noOfClerks; i++){
		len = Sprintf("isCuR",i,5);
		isCuR[i] = CreateMV(name, len, FALSE);
	}

	sgCk = CreateMV("sgCk", 4, -1);


	for(i=0; i<noOfCashReg; i++){
		len = Sprintf("crCuA",i,5);
		crCuA[i] = CreateMV(name, len, 0);

		len = Sprintf("crTtl",i,5);
		crTtl[i] = CreateMV(name, len, 0);

		len = Sprintf("crTSl",i,5);
		crTSl[i] = CreateMV(name, len, 0);
	}

	for(i=0; i<noOfCashReg; i++){
		len = Sprintf("cRSt",i,4);
		cRSt[i] = CreateMV(name, len, NOT_SET);

		len = Sprintf("amNd",i,4);
		amNd[i] = CreateMV(name, len, 0);
	}


	noSBLL = CreateMV("noSBLL",6,0);

	tlCuEx = CreateMV("tlCuEx",6,0);

	wkUpCk = CreateMV("wkUpCk",6,FALSE);

	alCkOB = CreateMV("alCkOB",6,FALSE);

	stRS = CreateMV("stRS",4,-1);


	for(i=0; i<MAX_NO_OF_AISLE; i++){
		len = Sprintf("aslQy",i,5);
		aslQty[i] = CreateMV(name, len, 3);

		len = Sprintf("aHlpL",i,5);
		aHlpLL[i] = CreateMV(name, len, 0);
	}

	for(i=0; i<noOfStockBoys; i++){
		len = Sprintf("sbSt",i,4);
		sbSt[i] = CreateMV(name, len, -1);
	}


	for(i=0; i<noOfStockBoys; i++){
		len = Sprintf("sbC0Q",i,5);
		sbCustQA[i][0] = CreateMV(name, len, 0);

		len = Sprintf("sbC1Q",i,5);
		sbCustQA[i][1] = CreateMV(name, len, 0);
	}


}

/*This test case runs the entire simulation with minimum requirements*/
void testcase12()
{


	noOfClerks=3;
	noOfCashReg=3;
	noOfCustomers=20;
	noOfStockBoys=3;

	generateCmnTestParams();
}



/*====================================================================================
// Function Problem2() which is called for simulation of the Part 2 of Assignment 1
// Contains the Test Case Selection Menu in it.
//====================================================================================*/


void main()
{


	printLock = CreateLock("printLock",9);
	cusTCtrLk=CreateLock("cusTCtrLk",9);
	cRgTCtrLk=CreateLock("cRgTCtrLk",9);
	clkTCtrLk=CreateLock("clkTCtrLk",9);
	sbTCtrLk=CreateLock("sbTCtrLk",8);

	/* Call testcase with minimum requiements */
	testcase12();

	Customer();
}
